using System;
using System.Collections.Generic;
using NUnit.Framework;
using ValidationFramework.Reflection;

namespace ValidationFramework.Tests
{
	[TestFixture]
    public class MethodCacheTest
    {

		public static readonly RuntimeMethodHandle TestMethodHandle = typeof(MethodCacheTest).GetMethod("TestMethod").MethodHandle;

			public IList<ValidationError> TestMethod(int param1)
			{
				return ParameterValidationManager.TryValidate(this, TestMethodHandle, param1);
			}

        [Test]
        public void GetMethodWithHandle()
        {
            MethodCache.Clear();
			var methodDescriptor = MethodCache.GetMethod(TestMethodHandle);
            Assert.IsNotNull(methodDescriptor);
			Assert.AreEqual("TestMethod", methodDescriptor.Name);
        }
        [Test]
        public void GetMethodWithDelegate()
        {
            MethodCache.Clear();
			var methodDescriptor = MethodCache.GetMethod(new Func<int, IList<ValidationError>>(TestMethod));
            Assert.IsNotNull(methodDescriptor);
			Assert.AreEqual("TestMethod", methodDescriptor.Name);
        }

        [Test]
        public void NoDuplicateTest()
        {
            MethodCache.Clear();
			var methodDescriptor1 = MethodCache.GetMethod(TestMethodHandle);
			var methodDescriptor2 = MethodCache.GetMethod(TestMethodHandle);
            Assert.AreSame(methodDescriptor1, methodDescriptor2);
        }


        [Test]
        public void AddRuleProgrammatically()
        {
            MethodCache.Clear();
        	var methodCacheTest = new MethodCacheTest();
            // 0 is valid numberOfWheels because there are no validation rules yet.
            var list = methodCacheTest.TestMethod(0);
            Assert.AreEqual(0, list.Count);

            var rangeRule = new RangeRule<int>(null, false, 1, 2, true, true);

			var methodDescriptor = MethodCache.GetMethod(new Func<int, IList<ValidationError>>(TestMethod));
            var parameterDescriptor = methodDescriptor.Parameters["param1"];
            parameterDescriptor.Rules.Add(rangeRule, null);


            // 0 is an invalid numberOfWheels 
            list = methodCacheTest.TestMethod(0);
            Assert.IsNotNull(list[0]);

            // 1 and 2 are a valid numberOfWheels 
			list = methodCacheTest.TestMethod(1);
            Assert.AreEqual(0, list.Count);
			list = methodCacheTest.TestMethod(2);
            Assert.AreEqual(0, list.Count);

            // 3 is an invalid numberOfWheels 
			list = methodCacheTest.TestMethod(3);
            Assert.IsNotNull(list[0]);


            parameterDescriptor.Rules.Clear();

			list = methodCacheTest.TestMethod(0);
            Assert.AreEqual(0, list.Count);
        }
    }
}